Mybatis框架(4) —— 手动编写持久层实现类实现CRUD操作

简介

  • MyBatis环境搭建 的方式在前面已经详细的介绍过了,本文仍然通过映射配置文件,但不再使用代理持久层接口实现类的方式,而是使用手动编写持久层实现类的方式来进行MySQL数据库的CRUD操作。
  • 创建持久层接口实现类的方式在实际开发中并不常用,所以我会将本文的主题放在与使用代理持久层实现类方法的比较上。
  • 改变的内容主要是测试类和持久层接口实现类。

目录结构

  • src/main
    • java
      • cn/water/dao
        • impl
          • UserDaoImpl.java(持久层实现类)
        • UserDao.java(持久层接口)
      • cn/water/domain
        • User.java(实体类)
      • resources
        • cn/water/dao
          • UserDao.xml(映射配置文件)
        • SqlMapConfig.xml(MyBatis主配置文件)
  • src/tese
    • java
      • cn/water/test
        • MybatisTest.java(测试文件)

持久层接口

UserDao.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package cn.water.dao;

import cn.water.domain.User;

import java.util.List;

public interface UserDao {

/** 添加用户 */
void add(User user);

/** 更新用户 */
void update(User user);

/** 删除用户 */
void delete(Integer id);

/** 查询所有用户 */
List<User> findAll();

/** 查询单个用户 */
User findOne(Integer id);

/** 根据姓名模糊查询 */
List<User> findByName01(String name);
List<User> findByName02(String name);

/** 查询所有用户的数量 */
Integer findTotal();

/** 添加用户 + 返回ID */
/*Integer addReturnID(User user);*/

/** 根据QueryVo对象的条件,模糊查询 */
/*List<User> findByQueryVO(QueryVo queryVo);*/
}

映射配置文件

UserDao.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="cn.water.dao.UserDao">

<!-- 添加用户 -->
<!-- 参数类型 JavaBean,占位符 = 成员变量名的小写形式 -->
<select id="add" parameterType="cn.water.domain.User" >
INSERT INTO user VALUES ( #{id}, #{username}, #{birthday}, #{sex}, #{address} ) ;
</select>

<!-- 更新用户 -->
<select id="update" parameterType="cn.water.domain.User">
UPDATE user SET
username = #{username},
birthday = #{birthday},
sex = #{sex},
address = #{address}
WHERE
id = #{id} ;
</select>

<!-- 删除用户 -->
<!-- 参数类型 基本类型,占位符 = 方法参数名称 -->
<select id="delete" parameterType="INT" >
DELETE FROM user WHERE id = #{id};
</select>

<!-- 查询所有 -->
<select id="findAll" resultType="cn.water.domain.User">
SELECT * FROM user;
</select>

<!-- 查询单个用户 -->
<select id="findOne" parameterType="INT" resultType="cn.water.domain.User">
SELECT * FROM user WHERE id = #{id} ;
</select>

<!-- 根据姓名模糊查询 -->
<select id="findByName01" parameterType="java.lang.String" resultType="cn.water.domain.User">
SELECT * FROM user WHERE username LIKE #{username};
</select>
<select id="findByName02" parameterType="java.lang.String" resultType="cn.water.domain.User">
SELECT * FROM user WHERE username LIKE '%${value}%';
</select>

<!-- 查询所有用户的数量 -->
<select id="findTotal" resultType="INT" >
SELECT COUNT(*) FROM user;
</select>


</mapper>

持久层实现类

UserDaoImp.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package cn.water.dao;

import cn.water.domain.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.After;

import java.util.List;

public class UserDaoImp implements UserDao {

/** 私有成员变量 */
private SqlSessionFactory factory;
private SqlSession session;

/** 带参构造 */
/* 初始化操作: factory 和 session */
public UserDaoImp(SqlSessionFactory factory){
this.factory = factory;
session = factory.openSession();
}

/** 销毁操作 */
/* 释放资源 */
@After
public void destroy() {
session.close();
}



/** 添加用户 */
public void add(User user){
session.insert("cn.water.dao.UserDao.add", user);
session.commit();
};

/** 更新用户 */
public void update(User user){
session.update("cn.water.dao.UserDao.update", user);
session.commit();
};

/** 删除用户 */
public void delete(Integer id){
session.delete("cn.water.dao.UserDao.delete", id);
session.commit();

};

/** 查询所有用户 */
public List<User> findAll(){
return session.selectList("cn.water.dao.UserDao.findAll");
};

/** 查询单个用户 */
public User findOne(Integer id){
return session.selectOne("cn.water.dao.UserDao.findOne", id);
};

/** 根据姓名模糊查询 */
public List<User> findByName01(String name){
return session.selectList("cn.water.dao.UserDao.findByName01", name);
};
public List<User> findByName02(String name){
return session.selectList("cn.water.dao.UserDao.findByName02", name);
};

/** 查询所有用户的数量 */
public Integer findTotal(){
return session.selectOne("cn.water.dao.UserDao.findTotal");
};


}

测试类

Test.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package cn.water.test;

import cn.water.dao.UserDao;
import cn.water.dao.UserDaoImp;
import cn.water.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;


public class UserTest {

/* 成员变量 */
private InputStream inputStream;
private SqlSession session;
private UserDao dao;

/* 初始化操作 */
@Before
public void init() throws IOException {
/* 加载 MyBatis配置文件 */
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
/* 获取 工厂类 */
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
/* 获取 持久层实现类 */
dao = new UserDaoImp(factory);
}

/* 销毁操作 */
@After
public void destroy() throws IOException {
inputStream.close();
}


/** 添加用户 */
@Test
public void test01(){
dao.add( new User(100,"ADD",new Date(),"男","UserDao") );
}

/** 更新用户 */
@Test
public void test02(){
dao.update( new User(100,"UPDATE",new Date(),"男","UserDao") );
}

/** 删除用户 */
@Test
public void test03(){
dao.delete(100);
}

/** 查询所有用户 */
@Test
public void test04(){
for (User user : dao.findAll()) {
System.out.println(user);
}
}

/** 查询单个用户 */
@Test
public void test05(){
System.out.println( dao.findOne(41) );
}


/** 根据用户模糊查询 */
@Test
public void test06(){
// LIKE #{username} 使用的是PreparedStatement对象
List<User> userList1 = dao.findByName01("%王%");
// LIKE '%${value}%' 使用的是Statement对象
List<User> userList2 = dao.findByName02("王");
/* 输出 */
for (User user : userList1) {
System.out.println("1--"+user);
}
for (User user : userList2) {
System.out.println("2--"+user);
}
}

/** 查询所有用户的数量 */
@Test
public void test07(){
System.out.println( dao.findTotal() );
}


}

ProxyDao vs MyDao

  • ProxyDao 和 MyDao 的具体区别在于:
    • 当我们使用代理持久层实现类的方式时,代理对象会帮我们增强代码去调用 selectList方法;
    • 但是当我们使用手动编写持久层实现类的方式时,我们就需要自己去编写实现类实现方法去调用 selectList方法了。
  • 而且我们不难发现,都是实现同一个功能,在测试类中 ProxyDao 比 MyDao 多了2行代码。但恐怖的是,MyDao 比 ProxyDao 多了一个类。

ProxyDao

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* 1.加载 MyBatis配置文件 */
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
/* 2.获取 工厂类 */
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

/* 3.获取 产品类 */
session = factory.openSession();
/* 4.获取 代理对象 */
dao = session.getMapper(UserDao.class);
/* 5.调用方法 */
dao.add( new User(100,"ADD",new Date(),"男","UserDao") );
/* 6.提交事务 */
session.commit();

/* 7.释放资源 */
session.close();
inputStream.close();

MyDao

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
/* 1.加载 MyBatis配置文件 */
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
/* 2.获取 工厂类 */
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

/* 3.获取 持久层实现类 */
dao = new UserDaoImp(factory);

/* 5.调用方法 */
dao.add( new User(100,"ADD",new Date(),"男","UserDao") );

/* 7.释放资源 */
inputStream.close();

实现类

1
2
3
4
5
6
7
/* 5.调用方法 */
session.insert("cn.water.dao.UserDao.add", user);
/* 6.提交事务 */
session.commit();

/* 7.释放资源 */
session.close();

实现CRUD操作

  • 本章节抛开了获取代理持久层实现类或持久层实现类的代码,以便直接显示 ProxyDao 和 MyDao 的具体区别。
  • 我们可以明显的看出 MyDao 代码的臃肿,所以这也是为什么手动编写持久层实现类的方法在实际编程中不受欢迎的原因了。

思维导图

![](4.MyDao CRUD操作/ProxyDao MyDao 区别.png)

添加用户

ProxyDao

  • 测试类
1
2
dao.add( new User(100,"ADD",new Date(),"男","UserDao") );
session.commit();

MyDao

  • 测试类
1
dao.add( new User(100,"ADD",new Date(),"男","UserDao") );
  • 实现类
1
2
3
4
public void add(User user){
session.insert("cn.water.dao.UserDao.add", user);
session.commit();
};

更新用户

ProxyDao

  • 测试类
1
2
dao.update( new User(100,"UPDATE",new Date(),"男","UserDao") );
session.commit();

MyDao

  • 测试类
1
dao.update( new User(100,"UPDATE",new Date(),"男","UserDao") );
  • 实现类
1
2
3
4
public void update(User user){
session.update("cn.water.dao.UserDao.update", user);
session.commit();
};

删除用户

ProxyDao

  • 测试类
1
2
dao.delete(100);
session.commit();

MyDao

  • 测试类
1
dao.delete(100);
  • 实现类
1
2
3
4
public void delete(Integer id){
session.delete("cn.water.dao.UserDao.delete", id);
session.commit();
};

查找所有用户

ProxyDao

  • 测试类
1
2
3
for (User user : dao.findAll()) {
System.out.println(user);
}

MyDao

  • 测试类
1
2
3
for (User user : dao.findAll()) {
System.out.println(user);
}
  • 实现类
1
2
3
public List<User> findAll(){
return session.selectList("cn.water.dao.UserDao.findAll");
};

查询单个用户

ProxyDao

  • 测试类
1
System.out.println( dao.findOne(41) );

MyDao

  • 测试类
1
System.out.println( dao.findOne(41) );
  • 实现类
1
2
3
public User findOne(Integer id){
return session.selectOne("cn.water.dao.UserDao.findOne", id);
};

根据姓名模糊查询

ProxyDao

  • 测试类
1
2
3
4
5
6
7
8
9
List<User> userList1 = dao.findByName01("%王%");
List<User> userList2 = dao.findByName02("王");

for (User user : userList1) {
System.out.println("1--"+user);
}
for (User user : userList2) {
System.out.println("2--"+user);
}

MyDao

  • 测试类
1
2
3
4
5
6
7
8
9
List<User> userList1 = dao.findByName01("%王%");
List<User> userList2 = dao.findByName02("王");

for (User user : userList1) {
System.out.println("1--"+user);
}
for (User user : userList2) {
System.out.println("2--"+user);
}
  • 实现类
1
2
3
4
5
6
7
public List<User> findByName01(String name){
return session.selectList("cn.water.dao.UserDao.findByName01", name);
};

public List<User> findByName02(String name){
return session.selectList("cn.water.dao.UserDao.findByName02", name);
};

查询所有用户数量

ProxyDao

  • 测试类
1
System.out.println( dao.findTotal() );

MyDao

  • 测试类
1
System.out.println( dao.findTotal() );
  • 实现类
1
2
3
public Integer findTotal(){
return session.selectOne("cn.water.dao.UserDao.findTotal");
};

执行过程(思维流图)

查询方法

![](4.MyDao CRUD操作/MyDao 查询操作 底层.png)

增删改方法

![](4.MyDao CRUD操作/MyDao 增删改操作 底层.png)

-------------本文结束-------------
Donate comment here